package com.tqw.item.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.net.UnknownHostException;

/**
 * redis序列化定制
 */
@Configuration
public class RedisConfig {
    /**
     * RedisTemplate高度定制,也可以参考ruoyi.vip的项目源码
     * @param redisConnectionFactory
     * @return
     * @throws UnknownHostException
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Object> template =
                new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //修改默认序列化方式
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(jsonSerializer());
        template.setHashKeySerializer(RedisSerializer.string());
        template.setHashValueSerializer(jsonSerializer());
        //建议template对象序列化方式修改以后,更新一下template对象内部的属性值
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public RedisSerializer jsonSerializer(){
        //1.构建与JSON相关的RedisSerializer类型的对象
        Jackson2JsonRedisSerializer redisSerializer=
                new Jackson2JsonRedisSerializer(Object.class);
        //2.设置序列化规则
        ObjectMapper objectMapper=new ObjectMapper();
        //2.1设置基于哪些方法规则进行序列化
        objectMapper.setVisibility(
                PropertyAccessor.GETTER, //只针对get方法有效
                JsonAutoDetect.Visibility.ANY);//any表示任意访问修饰符
        //2.2设置要序列化的内容(例如为null时是否序列化)
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //2.3激活类型存储(序列化时,也存储当前对象的类型)
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL,//序列化的类不能使用final修饰
                JsonTypeInfo.As.PROPERTY);//PROPERTY表示存储的类型会以属性形式存储
        redisSerializer.setObjectMapper(objectMapper);
        //3.返回序列化对象
        return redisSerializer;
    }
}
